/**
*   FuzzyEngine - an Simple flex framework 
*   Copyright (C) 2010 Constantin Aldea
*
*   This program is free software: you can redistribute it and/or modify
*   it under the terms of the GNU General Public License as published by
*   the Free Software Foundation, either version 3 of the License, or
*   (at your option) any later version.
*   This program is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU General Public License for more details.
*
*   You should have received a copy of the GNU General Public License
*   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package fuzzy.penelope.model {
	import fuzzy.penelope.controller.GenericController;
	import fuzzy.penelope.core.dataservices.rest.IServiceFuzzy;
	import fuzzy.penelope.core.dataservices.rest.Service;
	import fuzzy.penelope.helpers.instantiator.Instantiator;
	import fuzzy.penelope.model.vo.framework.exceptions.ServiceException;
	import fuzzy.penelope.model.vo.framework.exceptions.SystemException;

	import project.enums.AppConfigKeyEnum;

	import mx.controls.Alert;
	import mx.managers.CursorManager;

	import flash.events.EventDispatcher;
	import flash.utils.Dictionary;

	[Bindable]
	public class ContextManager extends EventDispatcher
	{
		
		private static var instance:ContextManager;
		public function ContextManager()
		{
			
			service = Service.getInstance();
			context = Context.getInstance();
			
		}
		
		
		public static function getInstance():ContextManager{
			if(instance != null){
				return instance;
			}else{
				return instance = new ContextManager;
			}
		}
		

		
		public var context:ContextImpl;
		public  var service:IServiceFuzzy;
	
		public function handleExceptions(val:Object):void{			
			if(val is SystemException){
				Alert.show((val as SystemException).detailMessage, AppConfigKeyEnum.WARNING);
			}else if(val is ServiceException){
				Alert.show((val as ServiceException).detailMessage, AppConfigKeyEnum.WARNING);
			}else{
				Alert.show("Errore di sistema, probabilmente la risposta del server e null", AppConfigKeyEnum.WARNING);
			}
			CursorManager.removeAllCursors();
			ContextManager.getInstance().context.contextLoader.removeLoading();
			
		}
		
		/**
		 * 
		 * @param VO la classe che contiene la costante MODULE_NAME (nome del modulo da chiamare in fuzzy) 
		 * @param clazz La classe da instanziare quando si richiama getController
		 * @
		 * <code>
		 *   ContextManager.getInstance().registerController(Albero, AlberoController);
		 * </code>
		 */		
		public  function registerController(vo:Class, clazz:Class):Boolean{
			if(!vo.hasOwnProperty(GenericController.MODULE_IDENTIFIER)){
				throw new Error("Il controller deve implementare l'atributo public static const "+ GenericController.MODULE_IDENTIFIER + " " + 
						" corrispondente al nome del modulo fuzzy da chiamare ");
				return false;
			}
			
			if(!(clazz is GenericController)){
				throw new Error("I controller devono estendere i generic controller per poter esssere registrati");
				return false;
			}
			
			_map[vo] = clazz;
			return true;
		}
		
		//dictionary di prototipi		private var _map:Dictionary=new Dictionary;
		
		//dictionary di instances
		private var _instanceMap:Dictionary=new Dictionary;
				
		/**
		 * 
		 * @param vo La classe che contine la costante MODULE_NAME con il nome(alias) del modulo da chiamare
		 * @return torna un instanza del controller registrato con questa classe
		 * <code>
		 * 	 ContextManager.getInstance().getController(Albero).caricaPermessi();
		 * 	 * se si vuole sfruttare il code hinting per la classe controller si puo fare un cast
		 *    (ContextManager.getInstance().getController(Albero) as AlberoController).caricaPermessi();	
		 * </code>
		 */				
		public function getController(vo:Class):Class{
			//se e null, non c'e stato registrato un controller
			if(_map[vo] == null){
					throw new Error("non e stato registrato nessun controller per questa tipo di oggetto");
			} else{
				//se c'e allora dobbiamo fornire l'instanza dalla mappa di controller
			
				if(_instanceMap[_map[vo]] == null){
					_instanceMap[_map[vo]] = Instantiator.newInstance(_map[vo]);
				}
				
				return _instanceMap[_map[vo]];
				
			} 	
		} 

		
	}
}